在建立一個網站服務時,我們經常會使用到 redirect。
此處舉一個例子,遇到的需求可能會像是: 我們想要導向外部網站的服務。
雖然 Redirect 有時可以帶給用戶良好的體驗,但若沒有適當處理就有可能會默默為我們埋下未爆彈,就默默讓用戶導向惡意網站了。
採用發送垃圾郵件來釣魚:
以下為範例 url:
https://your_website.com/signin?redirect_uri=https://your_website_xxoo.coom/
攻擊者嘗試將導向的網站替換成他們想要你被導向的惡意網站
(惡意網站通常會有相似的網站名稱)
->
讓人在不經意間相信了該網站是我們原本正在造訪的網站
->
最後輸入我們的訊息給惡意網站
(例如:帳號/密碼) or 不小心下載到惡意程式
此處需要注意的是:
如果他們可以將用戶“退回”到您的網站(一個明顯有效的域),他們的消息就不太可能被標記為惡意。如果用戶點擊該 link,使用者將在 link 中看到您的網站,但他們最終會到達攻擊者想要將他們導向到的任何站點。
以 NodeJS 為例,在處理跨域 url 的時候,記得**不要**直接無意識 redirect,對要導向的網站毫無掌握
app.post('/buyItems', (req, res) => {
// 像是在此處我們就直接導向 "req.query.redirect_url",沒有設立任何 allowlist 也沒過濾就導向了
res.redirect(req.query.redirect_url ? req.query.redirect_url : '/');
});
此處皆以 NodeJS 為例:
建立 allowList,只允許導向 allowlist 中的 url
app.post('/buyItems', (req, res) => {
const allowlist = ['/test1', '/test2'];
if (allowlist.indexOf(req.query.redirect_url) > -1) {
res.redirect(req.query.redirect_url);
} else {
res.redirect('/');
}
});
禁止任何 Offsite Redirects
可以通過檢查 URL 來防止 redirect 到其他域,所以我們需要確保所有 redirect URL 都是相對路徑
(即它們以單個 /
字符開頭)。
// redirect 前,可以使用以下方式來確認是否為 '/' 開頭的 url
function getValidRedirect(url) {
// 確認你的 url 是否是 '/' 開頭
if (url.match(/^\/(?!\/)/)) {
if (process.env.NODE_ENV == "development") {
return '//127.0.0.1:3000' + url;
}
// For production
return '//www.your_website.com' + url;
}
}
注意!!:
以 //
開頭的 URL 將被 Browser 解釋為與協議無關的絕對 URL —— 它們應該被拒絕。
當要 Redirects 時,確認 Referrer
:
Redirect 到 query string 中傳遞的 URL 應該只由您網站上的頁面觸發。
我們應該對任何觸發 redirect 的網站抱持懷疑態度,所以在執行 Redirects 的時候,請檢查 HTTP 請求中的 Referer 是否與您的域匹配
。
範例:
// 在 express 4 之後,我們可以使用 req.get('Referrer') 來取得 referrer
req.get('Referrer');
小百科:
這邊的 HTTP Referrer
(referer)是 HTTP header 的一個欄位,用來表示從哪個連結來到目前的網頁,採用的格式是 URL。
-> 藉著 HTTP Referrer
,目前的網頁可以檢查訪客從哪裡而來,這也常被用來對付偽造的跨網站請求
。
確認 Client-Side Code
確保在使用 window.location
時,url 不會接收到不被信任的 input:
也就是我們不要完全信賴使用者給我們的 Input 作為重新導向的 link
。
Redirect 要注意的事情真的是滿多的,如果真的要寫還會需要寫到 XSS 相關的攻擊,任何跟 url 相關的都不能放過,看來明日是需要來肝一下了,繼續加油!